package cn.com.dcsgo.aspectj;

import com.alibaba.fastjson2.JSON;
import io.swagger.v3.oas.annotations.Operation;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.ObjectUtils;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.context.annotation.EnableAspectJAutoProxy;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

/**
 * HTTP接口日志切面
 *
 * @author Dcsgo
 * @since 2025/10/13 16:00
 */
@Slf4j
@Aspect
@Component
@EnableAspectJAutoProxy
public class MyLogAspect {
    /**
     * 切点
     */
    public static final String POINT_CUT = "execution (* cn.com.dcsgo.controller.*.*(..))";

    @Around(POINT_CUT)
    public Object logAround(ProceedingJoinPoint joinPoint) throws Throwable {
        //得到请求对象
        ServletRequestAttributes requestAttributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
        assert requestAttributes != null;
        HttpServletRequest request = requestAttributes.getRequest();
        //得到用户请求的 URI   http://localhost:60010/user/addUser
        String uri = request.getRequestURI();
        //得到客户端IP
        String ip = request.getRemoteAddr();
        //得到目标方法的入参
        Object[] args = joinPoint.getArgs();
        //拿类型和方法名称
        MethodSignature signature = (MethodSignature) joinPoint.getSignature();
        //得到方法对象
        Method method = signature.getMethod();
        //从方法对象里面得到方法名称
        String methodName = method.getName();
        //得到方法所在类(cn.com.dcsgo.controller.UserController)
        Class<?> aClass = method.getDeclaringClass();
        //得到类名
        String typeName = aClass.getTypeName();
        //取方法的描述
        String desc = "";
        if (method.isAnnotationPresent(Operation.class)) {
            Operation operation = method.getDeclaredAnnotation(Operation.class);
            desc = operation.summary();
        }
        //记录开始时间
        long start = System.currentTimeMillis();
        //执行目标方法
        Object result = joinPoint.proceed();
        //记录结束时间
        long end = System.currentTimeMillis();
        //耗时
        long spendTime = end - start;
        //处理文件上传入参的问题
        String finalArgs;
        if (!ObjectUtils.isEmpty(args) && args[0] instanceof MultipartFile) {
            finalArgs = "file";
        } else {
            finalArgs = JSON.toJSONString(args);
        }
        log.info("调用时间:{},路径为:{},ip为:{},方法为:{},执耗时为:{}ms,描述:{},参数为:{},结果为:{}",
                LocalDateTime.now(),
                uri,
                ip,
                typeName + "." + methodName,
                spendTime,
                desc,
                finalArgs,
                JSON.toJSONString(result)
        );
        return result;
    }
}
